#include "dspSimulator/instruction/MVK.h"

std::shared_ptr<Instruction> MVK::decode(std::shared_ptr<InstInfo> instInfo, u64 baseCycle) {
    std::shared_ptr<MVK> mvk;
    auto dspInstInfo = std::dynamic_pointer_cast<DspInstInfo>(instInfo);
    bool isStandardInst = dspInstInfo->isStandardInstruction();
    if (isStandardInst) {
        // Standard指令
        auto data = vectorToBitSet<32>(dspInstInfo->getBits());
        if (checkBits<5>(data, 2, 0b01010) && existStandardCondition(data)) {
            // MVK (.unit) scst16, sint
            mvk = std::make_shared<MVK>(dspInstInfo->getAddress(), baseCycle);
            mvk->creg_z = extractBits<4>(data, 28);
            u32 dst = extractBits<5>(data, 23).to_ulong();
            u32 cst = extractBits<16>(data, 7).to_ulong();
            bool s = data[1];
            mvk->p = data[0];
            if (s) {
                mvk->funcUnit = FuncUnit::S1;
            } else {
                mvk->funcUnit = FuncUnit::S2;
            }
            mvk->m_op1 = std::make_shared<Immediate32>(extractBitsAndToInt<16>(cst));
            mvk->m_op2 = std::make_shared<SingleReg>(getDstReg32Kind(dst, s));
        }
    }
    return mvk;
}

void MVK::generateIR(std::shared_ptr<IRGenerator> irGenerator, llvm::Function *function, RegCopy &regCopy) {
    if (funcUnit == FuncUnit::S1 || funcUnit == FuncUnit::S2) {
        generateIRInS(irGenerator, function, regCopy);
    }
}

std::string MVK::toString() {
    std::string str;
    auto imm = std::dynamic_pointer_cast<Immediate32>(m_op1);
    auto dstReg = std::dynamic_pointer_cast<SingleReg>(m_op2);
    str = m_name + " " + FuncUnitName[static_cast<u32>(funcUnit)] + " " + dec2hex(imm->getData()) +
          "," + dstReg->toString();
    return str;
}

void MVK::generateIRInS(std::shared_ptr<IRGenerator> irGenerator, llvm::Function *function, MVK::RegCopy &regCopy) {
    auto irBuilder = irGenerator->getLLVMIRBuilder();
    auto module = irGenerator->getLLVMModule();
    if (!isCompactInstruction) {
        auto cst = std::dynamic_pointer_cast<Immediate32>(m_op1);
        auto dst = std::dynamic_pointer_cast<SingleReg>(m_op2);
        if (cst && dst) {
            auto scst16 = cst->getData();
            auto dstRegName = getRegName(dst->getReg());
            auto dstRegPtr = module->getNamedGlobal(dstRegName);
            irBuilder->CreateStore(irBuilder->getInt32(scst16), dstRegPtr);
        }
    }
}


